package service

import (
	"192.168.1.75/go-pkg/helper"

	"context"
	"errors"
	"fmt"
	"mini-app/config/mysql"
	"mini-app/config/redis"
	"mini-app/internal/app/grpc/client"
	"mini-app/internal/app/grpc/common"
	"mini-app/internal/app/grpc/protoc/sale_adminc"
	"mini-app/internal/app/grpc/protoc/system_admin"
	"mini-app/internal/dal"
	"mini-app/internal/dao"
	"mini-app/internal/define"
	"mini-app/internal/models"
	"mini-app/internal/pkg"
	"strconv"

	"time"

	"192.168.1.75/go-pkg/errorx"
	"192.168.1.75/go-pkg/logx"
	"github.com/samber/lo"
	"gorm.io/gorm"
)

type OnlineEvent struct{}

func (OnlineEvent) Create(ctx context.Context, record models.OnlineEvent) (string, error) {
	SystemAdminClient, clientErr := client.GetSystemAdminClient()
	if clientErr != nil {
		return "", errorx.New("商品图片上传失败", -1)
	}

	{
		now := time.Now()
		if record.Visible == define.State_Yes {
			nowBefore30Days := now.AddDate(0, 0, -30)
			if record.EndTime < nowBefore30Days.Unix() {
				return "", errorx.New("活动已结束30天，不可再显示;请检查活动结束时间和可见设置", -1)
			}
		}
	}

	// 获取商品类型
	saleAdminClient, saleAdminClientErr := client.GetSaleAdminClient()
	if saleAdminClientErr != nil {
		logx.Error(ctx, "connect sale admin grpc error", logx.Any("saleAdminClientErr", saleAdminClientErr))
		return "", errorx.New("获取商品信息失败", -1)
	}
	rsp, err := saleAdminClient.GoodsDetail(ctx, &sale_adminc.GoodsDetailReq{GoodsId: record.GoodsID})
	if err != nil {
		return "", errorx.New("获取商品信息失败", -1)
	}
	if rsp.GoodsId == "" {
		return "", errorx.New("商品不存在", -1)
	}
	if rsp.GoodsType != 8 {
		return "", errorx.New("商品类型必须是活动商品", -1)
	}
	// 确认商品图片
	{
		var req system_admin.ConfirmFileReq
		req.FileUrl = record.Image
		rsp, err1 := SystemAdminClient.ConfirmFile(context.Background(), &req)
		if err1 != nil && rsp.Code != 0 {
			return "", errorx.New("商品图片上传失败", -1)
		}
		record.Image = rsp.FileUrl
	}
	// 确认详情图片
	if record.Description != "" {
		record.Description = pkg.RichTextConvert(record.Description)
	}

	var id string
	id, err = dao.OnlineEvent{}.Create(ctx, mysql.NewDB(), record)
	if err != nil {
		return "", errorx.New(fmt.Sprintf("创建活动失败: %s", err.Error()), -1)
	}

	return id, nil
}

func (OnlineEvent) Update(ctx context.Context, record models.OnlineEvent) error {
	SystemAdminClient, clientErr := client.GetSystemAdminClient()
	if clientErr != nil {
		return errorx.New("商品图片上传失败", -1)
	}
	detail := dao.OnlineEvent{}.Detail(ctx, mysql.NewDB(), record.ID)
	if detail == nil {
		return errorx.New("活动不存在", -1)
	}

	{
		// 活动已结束30天，不可再显示
		now := time.Now()
		visible := detail.Visible
		if record.Visible != 0 {
			visible = record.Visible
		}
		if visible == define.State_Yes {
			endTime := detail.EndTime
			if record.EndTime != 0 {
				endTime = record.EndTime
			}
			nowBefore30Days := now.AddDate(0, 0, -30) //
			if endTime < nowBefore30Days.Unix() {
				return errorx.New("活动已结束30天，不可再显示;请检查活动结束时间和可见设置", -1)
			}
		}
	}

	// 获取商品类型
	if record.GoodsID != "" {
		saleAdminClient, saleAdminClientErr := client.GetSaleAdminClient()
		if saleAdminClientErr != nil {
			logx.Error(ctx, "connect sale admin grpc error", logx.Any("saleAdminClientErr", saleAdminClientErr))
			return errorx.New("获取商品信息失败", -1)
		}
		rsp, err := saleAdminClient.GoodsDetail(ctx, &sale_adminc.GoodsDetailReq{GoodsId: record.GoodsID})
		if err != nil {
			return errorx.New("获取商品信息失败", -1)
		}
		if rsp.GoodsId == "" {
			return errorx.New("商品不存在", -1)
		}
		if rsp.GoodsType != 8 {
			return errorx.New("商品类型必须是活动商品", -1)
		}
	}
	// 确认商品图片
	if record.Image != "" && detail.Image != record.Image {
		var req system_admin.ConfirmFileReq
		req.FileUrl = record.Image
		rsp, err1 := SystemAdminClient.ConfirmFile(context.Background(), &req)
		if err1 != nil && rsp.Code != 0 {
			return errorx.New("商品图片上传失败", -1)
		}
		// 删除旧的图片
		if detail.Image != "" {
			SystemAdminClient.DeleteFile(context.Background(), &system_admin.DeleteFileReq{
				FileUrl: detail.Image,
			})
		}
		record.Image = rsp.FileUrl
	}
	// 确认详情图片
	if record.Description != "" {
		record.Description = pkg.RichTextConvert(record.Description)
	}
	err := dao.OnlineEvent{}.Update(ctx, mysql.NewDB(), record)
	if err != nil {
		return errorx.New("更新活动失败", -1)
	}
	return nil
}

func (OnlineEvent) Delete(ctx context.Context, ID string) error {
	err := dao.OnlineEvent{}.Delete(ctx, mysql.NewDB(), ID)
	if err != nil {
		return errorx.New("删除活动失败", -1)
	}
	return nil
}

func (OnlineEvent) Detail(ctx context.Context, ID string) *models.OnlineEvent {
	record := dao.OnlineEvent{}.Detail(ctx, mysql.NewDB(), ID)
	if record == nil {
		return nil
	}
	nowTS := time.Now().Unix()
	if nowTS >= record.StartTime && nowTS <= record.EndTime {
		record.Status = 2 // 进行中
	} else if nowTS < record.StartTime {
		record.Status = 1 // 未开始
	} else if nowTS > record.EndTime {
		record.Status = 3 // 已结束
	}
	return record
}

type OnlineEventListT struct {
	models.OnlineEvent
	TotalUser int64 `json:"total_user"` // 参与人数
}

func (OnlineEvent) List(
	ctx context.Context,
	name string,
	status int,
	page, limit int,
) (list []OnlineEventListT, total int64) {
	nowTS := time.Now().Unix()
	records, total := dao.OnlineEvent{}.List(ctx, mysql.NewDB(), name, status, define.State_Nil, define.State_Nil,
		page, limit)
	for _, record := range records {
		if record.Status == 0 {
			if nowTS >= record.StartTime && nowTS <= record.EndTime {
				record.Status = 1 // 进行中
			} else if nowTS < record.StartTime {
				record.Status = 2 // 未开始
			} else if nowTS > record.EndTime {
				record.Status = 3 // 已结束
			}

		}
		totalUser := dao.OnlineEventUser{}.Count(ctx, mysql.NewDB(), record.ID, 0)
		record.JoinedUser = totalUser
		list = append(list, OnlineEventListT{
			OnlineEvent: record,
			TotalUser:   totalUser,
		})
	}
	return list, total
}

func (t OnlineEvent) WinnerConfig(
	ctx context.Context,
	onlineEventID string,
	userID string,
	puppetUserID string,
) error {

	onlineEvent := dao.OnlineEvent{}.Detail(ctx, mysql.NewDB(), onlineEventID)
	if onlineEvent == nil {
		return errorx.New("活动不存在", -1)
	}

	userList, err := dao.OnlineEvent{}.ParsedUserIDs(userID)
	puppetUserList, err := dao.OnlineEvent{}.ParsedUserIDs(puppetUserID)
	if err != nil {
		return errorx.New(errors.Join(errors.New("内定中奖马甲用户ID解析失败"), err).Error(), -1)
	}

	if int64(len(puppetUserList)) > onlineEvent.BaseJoinedUser {
		return errorx.New("内定中奖马甲用户数量超出活动基础人数", -1)
	}

	if int64(len(userList)+len(puppetUserList)) > onlineEvent.LimitedFree {
		return errorx.New("内定中奖用户数量不能超出限免人数", -1)
	}

	err = dao.OnlineEvent{}.WinnerConfig(ctx, mysql.NewDB(), onlineEventID, userID, puppetUserID)
	if err != nil {
		return errorx.New(errors.Join(errors.New("中奖配置失败"), err).Error(), -1)
	}
	return nil
}

type WinnerListT struct {
	models.OnlineEventUser
	OrderStatus             int     `json:"order_status"`               // 订单状态
	ExpressFeePaymentStatus int     `json:"express_fee_payment_status"` // 邮费支付状态 0-无 1-已支付 2-未支付
	ExpressFee              float64 `json:"express_fee"`                // 邮费
	ShippingStatus          int     `json:"shipping_status"`            // 发货状态 1-已发货 2-待发货
}

func (OnlineEvent) WinnerList(
	ctx context.Context,
	onlineEventID string,
	page, limit int,
	IsPuppetUser bool,
) (list []WinnerListT, total int64, err error) {
	records, total, err := dao.OnlineEventUser{}.List(ctx, mysql.NewDB(), onlineEventID, 2, nil,
		nil, nil, &IsPuppetUser, page, limit)
	if err != nil {
		logx.Error(ctx, "get online event user list error", logx.Any("err", err))
		return nil, 0, errors.Join(errors.New("获取中奖列表失败"), err)
	}
	for _, record := range records {
		if record.IsPuppetUser == true {
			uid, _ := helper.StringToInt64(record.UserID)
			puppetUser, _ := dao.NewPuppetUserRepo(ctx).FindOneById(ctx, uid)
			if puppetUser != nil {
				record.WechatName = puppetUser.NickName
			}

			//是马甲的情况
			list = append(list, WinnerListT{
				OnlineEventUser: record,
			})
			continue
		}
		var orderStatus int
		var expressFeePaymentStatus int
		var expressFee float64
		var shippingStatus = 2
		// 微信名称
		userDetail, _ := dao.User{}.UserInfo(ctx, dal.Q, record.OpenID, "", "")
		if userDetail != nil {
			record.WechatName = userDetail.NickName
		}
		// 获取订单详情
		orderDetail, _ := dao.Order{}.Detail(ctx, dal.Q, "", "", record.OutTradeNo, "", "", 0)
		if orderDetail != nil {
			orderStatus = orderDetail.OrderStatus
			expressFee = orderDetail.ExpressFee
		}
		if expressFee == 0 {
			expressFeePaymentStatus = 0
		} else if orderStatus == define.OrderStatusUnpaid || orderStatus == define.OrderStatusUnPaidExpreeFee {
			expressFeePaymentStatus = 2
		} else {
			expressFeePaymentStatus = 1
		}
		// 查询发货状态
		expressNum, _ := common.GRPC{}.OrderShipmentInfo(ctx, record.OutTradeNo)
		if expressNum != "" {
			shippingStatus = 1
		}
		list = append(list, WinnerListT{
			OnlineEventUser:         record,
			ExpressFee:              expressFee,
			OrderStatus:             orderStatus,
			ExpressFeePaymentStatus: expressFeePaymentStatus,
			ShippingStatus:          shippingStatus,
		})
	}
	return
}

type OnlineEventUserListT struct {
	UserID            string `json:"user_id"`            // 用户id
	WechatName        string `json:"wechat_name"`        // 微信昵称
	WechatAvatar      string `json:"wechat_avatar"`      // 微信头像
	WinCount          int64  `json:"win_count"`          // 中奖计数
	CurrentSupporters int64  `json:"current_supporters"` // 助力人数
	IsPuppetUser      bool   `json:"is_puppet_user"`     // 是否马甲用户

}

func (OnlineEvent) UserList(
	ctx context.Context,
	onlineEventID string,
	page, limit int,
	isPuppetUser *bool,
) (list []OnlineEventUserListT, total int64, err error) {
	records, total, err := dao.OnlineEventUser{}.List(
		ctx,
		mysql.NewDB(),
		onlineEventID,
		0,
		[]string{},
		nil, nil,
		isPuppetUser,
		page, limit,
	)
	if err != nil {
		logx.Error(ctx, "get online event user list error", logx.Any("err", err))
		return nil, 0, errors.Join(errors.New("获取用户列表失败"), err)
	}

	for _, record := range records {
		if record.IsPuppetUser == true {
			uid, err := strconv.ParseInt(record.UserID, 10, 64)
			if err != nil {
				logx.Error(ctx, "get online event user list error", logx.Any("err", err))
				continue
			}
			puppetUser, err := dao.NewPuppetUserRepo(ctx).FindOneById(ctx, uid)
			if err != nil {
				logx.Error(ctx, "get online event user list error", logx.Any("err", err))
				continue
			}

			//是马甲的情况
			list = append(list, OnlineEventUserListT{
				UserID:            record.UserID,
				WechatName:        puppetUser.NickName,
				WechatAvatar:      puppetUser.Avatar,
				WinCount:          dao.OnlineEventUser{}.WinCount(ctx, mysql.NewDB(), record.UserID),
				CurrentSupporters: int64(record.CurrentSupporters),
				IsPuppetUser:      record.IsPuppetUser,
			})
			continue
		}
		image := ""
		name := ""
		userDetail, _ := dao.User{}.UserInfo(ctx, dal.Q, "", record.UserID, "")
		if userDetail != nil {
			image = userDetail.Image
			name = userDetail.NickName
		}
		list = append(list, OnlineEventUserListT{
			UserID:            record.UserID,
			WechatName:        name,
			WechatAvatar:      image,
			WinCount:          dao.OnlineEventUser{}.WinCount(ctx, mysql.NewDB(), record.UserID),
			CurrentSupporters: int64(record.CurrentSupporters),
			IsPuppetUser:      record.IsPuppetUser,
		})
	}
	return
}

func (t OnlineEvent) SelectedUserList(
	ctx context.Context,
	onlineEventID string,
	page, limit int,
) (list []OnlineEventUserListT, total int64, err error) {
	onlineEventDetail := dao.OnlineEvent{}.Detail(ctx, mysql.NewDB(), onlineEventID)
	if onlineEventDetail == nil {
		return nil, 0, errors.Join(errors.New("活动不存在"), err)
	}

	paresedSelectedUserID, err := dao.OnlineEvent{}.ParsedUserIDs(onlineEventDetail.SelectedUser)
	if err != nil {
		return
	}

	paresedSelectedPuppetUserID, err := dao.OnlineEvent{}.ParsedUserIDs(onlineEventDetail.SelectedPuppetUser)
	if err != nil {
		return
	}

	records, total, err := dao.OnlineEventUser{}.List(
		ctx,
		mysql.NewDB(),
		onlineEventID,
		0,
		[]string{},
		&paresedSelectedUserID, &paresedSelectedPuppetUserID,
		nil,
		page, limit,
	)
	if err != nil {
		logx.Error(ctx, "get online event user list error", logx.Any("err", err))
		return nil, 0, errors.Join(errors.New("获取用户列表失败"), err)
	}

	for _, record := range records {
		image := ""
		name := ""

		if record.IsPuppetUser != true {
			userDetail, _ := dao.User{}.UserInfo(ctx, dal.Q, "", record.UserID, "")
			if userDetail != nil {
				image = userDetail.Image
				name = userDetail.NickName
			}
		} else {
			uid, _ := strconv.ParseInt(record.UserID, 10, 64)
			userDetail, _ := dao.NewPuppetUserRepo(ctx).FindOneById(ctx, uid)
			if userDetail != nil {
				image = userDetail.Avatar
				name = userDetail.NickName
			}
		}

		list = append(list, OnlineEventUserListT{
			UserID:            record.UserID,
			WechatName:        name,
			WechatAvatar:      image,
			WinCount:          dao.OnlineEventUser{}.WinCount(ctx, mysql.NewDB(), record.UserID),
			CurrentSupporters: int64(record.CurrentSupporters),
			IsPuppetUser:      record.IsPuppetUser,
		})
	}
	return
}

// Draw 活动抽奖
func (t OnlineEvent) Draw(
	ctx context.Context,
	onlineEventID string,
) error {
	eventDetail := dao.OnlineEvent{}.Detail(ctx, mysql.NewDB(), onlineEventID)
	if eventDetail == nil {
		return errorx.New("活动不存在", -1)
	}
	if eventDetail.IsDraw == 1 {
		return errorx.New("活动已开过奖", -1)
	}
	// 中奖名额
	limitedFree := eventDetail.LimitedFree
	// 中奖名单的userID
	realWinnerIDs := []string{}              //真实用户中奖用户列表
	puppetWinnerIDs := []string{}            //马甲用户中奖用户列表
	selectedEventUserListByIDs := []string{} //内定用户id列表（使用活动用户id，以区分userID）
	openids := []string{}

	var eventWinners []models.OnlineEventUser
	// 内定名单
	if eventDetail.SelectedUser != "" || eventDetail.SelectedPuppetUser != "" {
		selectedUserIDs, _ := dao.OnlineEvent{}.ParsedUserIDs(eventDetail.SelectedUser)
		selectedPuppetUserIDs, _ := dao.OnlineEvent{}.ParsedUserIDs(eventDetail.SelectedPuppetUser)

		// 内定的活动用户（包括真实用户和马甲用户）
		selectedEventUserList, _, err := dao.OnlineEventUser{}.List(ctx, mysql.NewDB(), onlineEventID, 0,
			[]string{}, &selectedUserIDs, &selectedPuppetUserIDs, nil, 0, 0)
		if err != nil {
			logx.Error(ctx, "get online event user list error", logx.Any("err", err))
			return err
		}

		if len(selectedUserIDs)+len(selectedPuppetUserIDs) < int(eventDetail.LimitedFree) {
			eventWinners = selectedEventUserList
		} else {
			eventWinners = lo.Samples(selectedEventUserList, int(eventDetail.LimitedFree))
		}

		// 活动用户id列表，以区分userID
		selectedEventUserListByIDs = lo.Map(selectedEventUserList, func(item models.OnlineEventUser, index int) string {
			return item.ID
		})

		for _, winner := range eventWinners {
			if winner.IsPuppetUser == true {
				puppetWinnerIDs = append(puppetWinnerIDs, winner.UserID)
			} else {
				userInfo, _ := dao.User{}.UserInfo(ctx, dal.Q, "", winner.UserID, "")
				if userInfo == nil {
					continue
				}

				realWinnerIDs = append(realWinnerIDs, winner.UserID)
				openids = append(openids, userInfo.OpenID)
			}

		}
	}

	// 获取零售grpc客户端
	saleAdminClient, saleAdminClientErr := client.GetSaleAdminClient()
	if saleAdminClientErr != nil {
		logx.Error(ctx, "connect sale admin grpc error", logx.Any("saleAdminClientErr", saleAdminClientErr))
		return errorx.New("获取商品信息失败", -1)
	}
	return mysql.NewDB().Transaction(func(tx *gorm.DB) error {
		// 更新已中奖的状态
		err := dao.OnlineEventUser{}.SetWinnerByIds(ctx, tx, onlineEventID, selectedEventUserListByIDs)
		if err != nil {
			logx.Error(ctx, "update online event user status error", logx.Any("err", err))
			//	return errors.Join(errors.New("设置中奖用户失败"), err)
		}

		realWinnerIDsByEventID := []string{} //真实用户中奖用户列表（eventUserID）
		// 待抽奖的数量(真实用户抽奖，内定中奖之外名额的抽奖逻辑)
		if len(selectedEventUserListByIDs) < int(limitedFree) {
			users, _, err := dao.OnlineEventUser{}.List(ctx, tx,
				onlineEventID, 1, []string{"id", "user_id", "openid"},
				nil, nil, helper.BoolPtr(false), 0, 0)

			if err != nil {
				logx.Error(ctx, "get online event user list error", logx.Any("err", err))
				return errors.Join(errors.New("获取用户列表失败"), err)
			}

			drawUsers := lo.Samples(users, int(limitedFree)-len(selectedEventUserListByIDs))
			for _, user := range drawUsers {
				realWinnerIDs = append(realWinnerIDs, user.UserID)
				openids = append(openids, user.OpenID)
				realWinnerIDsByEventID = append(realWinnerIDsByEventID, user.ID)
			}
		}

		err = dao.OnlineEventUser{}.SetWinnerByIds(ctx, tx, onlineEventID, realWinnerIDsByEventID)
		if err != nil {
			logx.Error(ctx, "update online event user status error", logx.Any("err", err))
			//	return errors.Join(errors.New("设置中奖用户失败"), err)
		}
		// 更新参与用户的状态
		//err := dao.OnlineEventUser{}.SetWinner(ctx, tx, onlineEventID, realWinnerIDs, false)
		//if err != nil {
		//	logx.Error(ctx, "update online event user status error", logx.Any("err", err))
		//	return errors.Join(errors.New("设置中奖用户失败"), err)
		//}
		//
		//err = dao.OnlineEventUser{}.SetWinner(ctx, tx, onlineEventID, puppetWinnerIDs, true)
		//if err != nil {
		//	logx.Error(ctx, "update online event puppet user status error", logx.Any("err", err))
		//	return errors.Join(errors.New("设置中奖用户失败"), err)
		//}

		// 更新订单状态 -> 小样申请成功
		success := dao.OnlineEvent{}.UpdateOrderStatus(ctx,
			tx,
			onlineEventID,
			openids,
			define.OrderStatusApplyingSuccess,
		)
		if !success {
			return errorx.New("更新订单状态失败", -1)
		}
		// 不需要支付运费的，直接同步到零售后台
		{
			orderList := dao.Order{}.FreeExpressFeeList(ctx, mysql.NewDB(), onlineEventID)
			for _, order := range orderList {
				if lo.Contains(openids, order.Openid) {
					saleAdminClient.CreateOnlineOrder(context.Background(), &sale_adminc.CreateOnlineOrderReq{
						OutTradeNo: order.BatchID,
						List: []*sale_adminc.CreateOnlineOrderReq_List{
							{
								ChildOutTradeNo: order.ID,
								GoodsId:         order.GoodsID,
								Univalent:       order.Univalent,
								Count:           int32(order.Count),
							},
						},
						UserAddress: &sale_adminc.UserAddress{
							UserName:      order.UserName,
							TelNumber:     order.TelNumber,
							PostalCode:    order.PostalCode,
							ProvinceName:  order.ProvinceName,
							CityName:      order.CityName,
							CountyName:    order.CountyName,
							StreetName:    order.StreetName,
							DetailAddress: order.DetailAddress,
						},
						ExpressFee: order.ExpressFee,
					})
				}
			}
		}
		// 更新活动状态为已结束
		success = dao.OnlineEvent{}.End(ctx, tx, onlineEventID)
		if !success {
			return errorx.New("活动状态更新失败", -1)
		}

		// 更新活动状态为已结束
		success = dao.OnlineEvent{}.SetDraw(ctx, tx, onlineEventID)
		if !success {
			return errorx.New("已开奖状态更新失败", -1)
		}

		err = t.CancelTop(ctx, tx, onlineEventID)
		if err != nil {
			return errors.Join(errors.New("更新开奖状态后，取消置顶失败"), err)
		}

		err = t.SetSort(ctx, tx, onlineEventID, 0)
		if err != nil {
			return errors.Join(errors.New("更新已开奖状态后，取消排序失败"), err)
		}
		return nil
	})
}

// SetTop 设置置顶
func (OnlineEvent) SetTop(ctx context.Context, tx *gorm.DB, id string) error {
	rdb := redis.NewDB()
	lockKey := define.RedisEventActivityTopLock
	success, _ := rdb.SetNX(ctx, lockKey, 1, time.Second*5).Result() //防止重入
	if !success {
		return errorx.New("操作过于频繁，请稍后再试", -1)
	}

	defer rdb.Del(ctx, lockKey)

	const MaxTop = 15 //最大置顶数
	repo := dao.NewOnlineEventRepo(tx)

	//按照top、sort、创建时间排序查询出来
	list, total, err := repo.ListByFilter(ctx, &dao.OnlineEventListFilter{Top: 1},
		helper.NewPageInfo(1, 1000, nil))
	if err != nil {
		return errorx.New("查询活动列表失败", -1)
	}

	if len(list) >= MaxTop {
		return errorx.New(fmt.Sprintf("置顶数量已达到上限(%d个置顶)，请手动取消一个置顶", MaxTop), -1)
	}

	var top = 1
	if total != 0 && len(list) != 0 {
		top = list[0].Top + 1
	}

	rc, err := repo.FindOneById(ctx, id)
	if err != nil {
		return errorx.New(fmt.Sprintf("查询活动失败: %s", err.Error()), -1)
	}
	if rc == nil {
		return errorx.New(fmt.Sprintf("未查询到活动"), -1)
	}

	rc.Top = top
	err = repo.UpdateColById(ctx, rc, dal.Q.OnlineEvent.Top)
	if err != nil {
		return errorx.New(fmt.Sprintf("设置置顶失败: %s", err), -1)
	}
	return nil
}

// CancelTop 取消置顶
func (OnlineEvent) CancelTop(ctx context.Context, _tx *gorm.DB, id string) error {
	rdb := redis.NewDB()
	lockKey := define.RedisEventActivityTopLock
	success, _ := rdb.SetNX(ctx, lockKey, 1, time.Second*5).Result() //防止重入
	if !success {
		return errorx.New("操作过于频繁，请稍后再试", -1)
	}

	defer rdb.Del(ctx, lockKey)

	err := _tx.Transaction(func(tx *gorm.DB) error {
		repo := dao.NewOnlineEventRepo(tx)

		// 查询要取消置顶的记录
		rc, err := repo.FindOneById(ctx, id)
		if err != nil {
			return errorx.New(fmt.Sprintf("查询活动失败: %s", err.Error()), -1)
		}
		if rc == nil {
			return errorx.New("未查询到活动", -1)
		}

		// 如果本身就不是置顶，直接返回
		if rc.Top == 0 {
			return nil
		}

		// 取消置顶
		rc.Top = 0
		err = repo.UpdateColById(ctx, rc, dal.Q.OnlineEvent.Top)
		if err != nil {
			return errorx.New(fmt.Sprintf("取消置顶失败: %s", err), -1)
		}

		// 查询所有置顶记录，按top降序排列
		list, _, err := repo.ListByFilter(ctx, &dao.OnlineEventListFilter{Top: 1},
			helper.NewPageInfo(1, 1000, nil))
		if err != nil {
			return errorx.New("查询置顶列表失败", -1)
		}

		// 重新分配连续的top值
		for i, event := range list {
			newTop := len(list) - i // 从最大值开始递减
			if event.Top != newTop {
				event.Top = newTop
				err = repo.UpdateColById(ctx, event, dal.Q.OnlineEvent.Top)
				if err != nil {
					return errorx.New(fmt.Sprintf("更新置顶值失败: %s", err), -1)
				}
			}
		}

		return nil
	})

	return err
}

func (OnlineEvent) SetSort(ctx context.Context, _tx *gorm.DB, id string, sort int) error {

	return _tx.Transaction(func(tx *gorm.DB) error {
		repo := dao.NewOnlineEventRepo(tx)

		// 查询要设置sort的记录
		rc, err := repo.FindOneById(ctx, id)
		if err != nil {
			return errorx.New(fmt.Sprintf("查询活动失败: %s", err.Error()), -1)
		}
		if rc == nil {
			return errorx.New("未查询到活动", -1)
		}

		// 更新sort值
		rc.Sort = sort
		err = repo.UpdateColById(ctx, rc, dal.Q.OnlineEvent.Sort)
		if err != nil {
			return errorx.New(fmt.Sprintf("设置排序值失败: %s", err), -1)
		}

		return nil
	})
}

func (t OnlineEvent) SetVisible(
	ctx context.Context,
	onlineEventID string,
	visible int,
) (err error) {
	repo := dao.NewOnlineEventRepo(ctx)
	err = repo.UpdateColById(ctx, &models.OnlineEvent{ID: onlineEventID, Visible: visible}, dal.Q.OnlineEvent.Visible)
	if err != nil {
		logx.Error(ctx, "OnlineEvent.SetVisible", logx.Any("err", err))
		return errorx.New(fmt.Sprintf("更新活动可见性失败: %s", err.Error()), -1)
	}

	return nil
}
